package cn.buddha.jesja.test.core;

import cn.buddha.jesja.test.domain.Person;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.io.File;
import java.io.IOException;

/**
 * @author shihao
 * @description jackson core
 */
@Slf4j
public class JsonCore {

    /**
     * <pre>
     * jackson写json数据：JsonGenerator（json生成器）
     *
     * JsonGenerator只负责生成json数据,至于把生成好的json写到哪里去并不关心。
     * </pre>
     */
    @Test
    public void testJsonGenerator() {
        JsonFactory jsonFactory = new JsonFactory();
        try (
                // 使用 JsonFactory 工厂来创建 json生成器
                JsonGenerator jsonGenerator = jsonFactory.createGenerator(
                        new File("C:\\tmp\\file\\json.txt"),
                        JsonEncoding.UTF8);
        ) {
            // 把 json 写漂亮点
            jsonGenerator.useDefaultPrettyPrinter();

            // 开始写了,写对象和写数组一样,都有闭环的思路(有始有终)
            jsonGenerator.writeStartObject();

            // 对于json来说,每一段都分为写key和写value。
            // key 可以独立存在, value不可以。
            // 虽然说 key 可以独立存在，但是后面不能再有其他的元素
            // 1- 写 key 方法
//            jsonGenerator.writeFieldName("IamKey");

            // 2- 写对象
            // 由于value不可单独存在,所以在写value前必须先写key
            // 对象的key
            jsonGenerator.writeFieldName("person");
            // 对象的value,对象的value就是个对象
            jsonGenerator.writeStartObject();
            jsonGenerator.writeFieldName("nickname");
            jsonGenerator.writeString("蜡头");
            jsonGenerator.writeFieldName("life");
            jsonGenerator.writeNumber(49);
            jsonGenerator.writeEndObject();

            // 3- 写数组
            // 数组的key
            jsonGenerator.writeFieldName("array");
            jsonGenerator.writeStartArray();
            // 3-1 写string
            jsonGenerator.writeString("com.fan.animal.Dog");
            // 3-2 写对象
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("dogName", "naonao");
            jsonGenerator.writeEndObject();
            jsonGenerator.writeEndArray();

            // 5- 写 布尔
            jsonGenerator.writeFieldName("success");
            jsonGenerator.writeBoolean(true);

            // 6- 写 null
            jsonGenerator.writeFieldName("hehe");
            jsonGenerator.writeNull();

            // 组合写 key 和 value
            jsonGenerator.writeStringField("name", "和珅");
            jsonGenerator.writeNumberField("age", 18);

            // 7- 写对象
            /*
             *  如果要写pojo，则必须给 JsonGenerator 指定一个 ObjectCodec解码器 才能正常使用，否则抛出异常
             *  java.lang.IllegalStateException: No ObjectCodec defined for the generator, can only serialize simple
             *  wrapper types (没有给 json generator 设置 ObjectCodec解码器,只能序列化简单的包装类)
             */
            Person person = Person.builder().name("爱德华").age(999).build();
            jsonGenerator.writeObject(person);

            // 结束写
            jsonGenerator.writeEndObject();
        } catch (IOException e) {
            log.error("IO异常了", e);
        }
    }

    /**
     * jackson的json解析器
     *
     * @author shihao
     */
    @Test
    public void testJsonParse() {
        String jsonStr = "{\"name\":\"HaoEr\",\"age\":18}";
        Person person = Person.builder().build();

        JsonFactory jsonFactory = new JsonFactory();

        try (
                JsonParser jsonParser = jsonFactory.createParser(jsonStr);
        ) {
            // 只要还没结束 "}", 就一直读
            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
                String fieldName = jsonParser.getCurrentName();

                if ("name".equals(fieldName)) {
                    jsonParser.nextToken();
                    person.setName(jsonParser.getText());
                    continue;
                }

                if ("age".equals(fieldName)) {
                    jsonParser.nextToken();
                    person.setAge(jsonParser.getIntValue());
                }
            }
        } catch (IOException e) {
            log.error("IO异常了", e);
        }

        System.err.println(person);
    }

}
